package com.yunchao.library.socket.model.metadata

import com.yunchao.library.socket.constants.Limits
import com.yunchao.library.socket.extensions.getByteArray
import com.yunchao.library.socket.extensions.getString
import com.yunchao.library.socket.extensions.toReadOnlyBuffer
import com.yunchao.library.socket.utils.BufferPool

data class MetadataSyncRequest(
    val metadata: String,
    val metamark: ByteArray
) {
    init {
        require(metadata.length <= Limits.MAX_METADATA_SIZE) {
            "Metadata too large: ${metadata.length}"
        }
        require(metamark.size <= Limits.MAX_BYTE_ARRAY_SIZE) {
            "Metamark too large: ${metamark.size}"
        }
    }

    fun toByteArray(): ByteArray {
        val metadataBytes = metadata.encodeToByteArray()
        return BufferPool.use(4 + metadataBytes.size + 1 + metamark.size) { buffer ->
            buffer.apply {
                putInt(metadataBytes.size)
                put(metadataBytes)
                put(metamark.size.toByte())
                put(metamark)
            }
            buffer.array().copyOf(buffer.position())
        }
    }

    companion object {
        fun fromByteArray(bytes: ByteArray): MetadataSyncRequest {
            val buffer = bytes.toReadOnlyBuffer()
            return MetadataSyncRequest(
                metadata = buffer.getString(),
                metamark = buffer.getByteArray(buffer.get().toInt() and 0xFF)
            )
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false
        other as MetadataSyncRequest
        return metadata == other.metadata && metamark.contentEquals(other.metamark)
    }

    override fun hashCode(): Int {
        var result = metadata.hashCode()
        result = 31 * result + metamark.contentHashCode()
        return result
    }
}